<template>
  <Dialog
    :title="props.editId ? '修改' : '新增'"
    @handle-confirm="handleConfirm"
    @closed="handleDialogClosed"
    @open="handleDialogOpen"
  >
    <el-form
      ref="formEl"
      :model="userForm"
      :rules="props.editId ? editRules : addRules"
      label-width="100px"
      label-position="right"
      v-loading="formLoading"
    >
      <el-form-item label="登录名：" prop="userName">
        <el-input v-model="userForm.userName" placeholder="请输入登录名" />
      </el-form-item>
      <!-- <el-form-item label="姓：">
        <el-input v-model="userForm.surname" placeholder="请输入姓" />
      </el-form-item> -->
      <el-form-item label="姓名：" prop="name">
        <el-input v-model="userForm.name" placeholder="请输入名" />
      </el-form-item>
      <el-form-item label="密码：" prop="password">
        <el-input
          v-model="userForm.password"
          show-password
          placeholder="请输入密码"
        />
      </el-form-item>
      <el-form-item label="确认密码：" prop="confirmPassword">
        <el-input
          v-model="userForm.confirmPassword"
          show-password
          placeholder="请再次输入密码"
        />
      </el-form-item>
      <el-form-item label="邮箱：" prop="email">
        <el-input v-model="userForm.email" placeholder="请输入邮箱" />
      </el-form-item>
      <el-form-item label="手机号：" prop="phoneNumber">
        <el-input v-model="userForm.phoneNumber" placeholder="请输入手机号" />
      </el-form-item>
      <el-form-item prop="lockoutEnabled">
        <el-checkbox v-model="userForm.lockoutEnabled">
          登录失败,账户被锁定
        </el-checkbox>
      </el-form-item>
      <el-form-item prop="isActive">
        <el-checkbox v-model="userForm.isActive"> 启用 </el-checkbox>
      </el-form-item>
      <el-form-item label="角色：" prop="roleNames">
        <el-checkbox-group v-model="userForm.roleNames">
          <el-checkbox
            v-for="role in roles"
            :key="role.id"
            :label="role.name"
          />
        </el-checkbox-group>
      </el-form-item>
    </el-form>
  </Dialog>
</template>

<script setup lang="ts">
import { ElMessage } from 'element-plus'
import { reactive, ref } from 'vue'

import Dialog from '@/components/Dialog/index.vue'
import { IListResult } from '@/http/types/base'
import type { IRole } from '@/http/types/role'
import { IUser, IUserData } from '@/http/types/user'
import {
  addUser,
  assignableRoles,
  getUser,
  getUserPermission,
  updateUser,
} from '@/http/user'
import type { IElForm } from '@/types/element-plus'
import { validPassword } from '@/utils/validate'
const props = defineProps({
  editId: {
    type: String,
    default: '',
  },
})
interface EmitsType {
  (e: 'update:editId', value: number | null): void
  (e: 'success', id: string): void
}
const emit = defineEmits<EmitsType>()

const data = {
  userName: '',
  name: '',
  password: '',
  confirmPassword: '',
  email: '',
  phoneNumber: '',
  lockoutEnabled: true,
  roleNames: [],
  concurrencyStamp: '',
  isActive: true,
}
const userForm = ref<IUserData>(data)

const roles = ref<Array<IRole>>([])
const validPassWords = (rule: any, value: any, callback: any) => {
  if (props.editId && value === '') {
    callback()
    return
  }
  const result = validPassword(value)
  if (result.length > 0) {
    callback(new Error(result[0]))
  }
  callback()
}
const validConfirmPassword = (rule: any, value: any, callback: any) => {
  if (props.editId && value === '') {
    callback()
    return
  }
  if (userForm.value.confirmPassword !== userForm.value.password) {
    callback(new Error('请确认两次密码一致！'))
  }
  callback()
}
const addRules = reactive({
  name: [{ required: true, message: '请输入姓名', trigger: 'blur' }],
  userName: [{ required: true, message: '请输入登录名', trigger: 'blur' }],
  password: [
    { required: true, message: '请输入密码', trigger: 'blur' },
    { validator: validPassWords, trigger: 'blur' },
  ],
  confirmPassword: [
    {
      required: true,
      message: '请再次输入密码',
      trigger: 'blur',
    },
    { validator: validConfirmPassword, trigger: 'blur' },
  ],
  email: [{ required: true, message: '请输入邮箱', trigger: 'blur' }],
})
const editRules = reactive({
  name: [{ required: true, message: '请输入姓名', trigger: 'blur' }],
  userName: [{ required: true, message: '请输入登录名', trigger: 'blur' }],
  password: [{ validator: validPassWords, trigger: 'blur' }],
  confirmPassword: [{ validator: validConfirmPassword, trigger: 'blur' }],
  email: [{ required: true, message: '请输入邮箱', trigger: 'blur' }],
})

const getAssignableRoles = async () => {
  const res = await assignableRoles()
  roles.value = res.items
  // 新增的时候选中默认值
  if (!props.editId) {
    const defaults: string[] = []
    roles.value.forEach((item) => {
      if (item.isDefault) {
        defaults.push(item.name)
      }
    })
    userForm.value.roleNames = defaults
  }
}

const formEl = ref<IElForm>()

const handleConfirm = async () => {
  try {
    await formEl.value?.validate()
    let res
    if (props.editId) {
      res = await updateUser(props.editId, userForm.value)
    } else {
      res = await addUser(userForm.value)
    }
    emit('success', res.id)
    ElMessage.success('保存成功')
  } catch (err) {
    console.error(err)
  }
}

const formLoading = ref(false)

const handleDialogOpen = async () => {
  formLoading.value = true
  await getAssignableRoles()
  await loadUser().finally(() => {
    formLoading.value = false
  })
}
const handleDialogClosed = () => {
  emit('update:editId', null)
  formEl.value?.resetFields() // 清除表单数据
  userForm.value.concurrencyStamp = ''
  roles.value = []
}
const loadUser = async () => {
  if (!props.editId) return
  Promise.all([getUser(props.editId), getUserPermission(props.editId)]).then(
    (res: [IUser, IListResult<IRole>]) => {
      const [data, { items }] = res
      userForm.value = {
        userName: data.userName,
        concurrencyStamp: data.concurrencyStamp,
        name: data.name,
        password: '',
        confirmPassword: '',
        email: data.email || '',
        phoneNumber: data.phoneNumber || '',
        lockoutEnabled: data.lockoutEnabled,
        roleNames: items.map((e) => e.name),
        isActive: data.isActive,
      }
    },
  )
}
</script>

<style scoped></style>
